package com.bs.service;

import com.bs.domain.AlertInfo;
import com.bs.domain.AlertMemo;
import com.bs.domain.SvcName;
import com.bs.repository.AlertMemoRepository;
import com.bs.repository.AlertTypeRepository;
import com.bs.repository.search.SvcNameSearchRepository;
import com.bs.service.callback.ModuleNameCallBack;
import com.bs.service.util.DateUtil;
import com.bs.utils.DataTable;
import com.bs.web.rest.util.HeaderUtil;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
 * Created by wujian
 * Date: 2017-12-14
 * Time: 13:23
 */
@Service
public class LogAlertService {

    private final Logger log = LoggerFactory.getLogger(LogAlertService.class);

    @Autowired
    private AlertTypeRepository alertTypeRepository;

    @Autowired
    private SvcNameSearchRepository svcNameSearchRepository;

    @Autowired
    private AlertMemoRepository alertMemoRepository;

    @Autowired
    private ModuleNameService moduleNameService;

    @Autowired
    private MailService mailService;

    @Autowired
    private MsgConfigService msgConfigService;

    public ResponseEntity serverDieAlert(String alertName, String time, String partition, String pid) {
        String svc = getSvc(partition, pid);
        if (svc == null) {
            return ResponseEntity.badRequest()
                .headers(HeaderUtil.createFailureAlert("SvcNotFound", "SvcNotFound", "SvcNotFound"))
                .body("ES_Query:SvcNotFound");
        }

        String sql = "SELECT SUB_SYSTEM_ENAME FROM TEA03 WHERE SVC_NAME='%s'";
        moduleNameService.getModule(partition, sql, svc, new ModuleNameCallBack() {

            @Override
            public void onSuccess(DataTable table) {
                String module;
                if (table.getRows().size() == 0) {
                    log.debug("无module数据");
                    module = "EMPTY";
                } else {
                    module = table.getValue(0, "SUB_SYSTEM_ENAME").toString();
                }
                sendEmailAndMessage(alertName, module, partition, svc, time, null, null, null);

            }

            @Override
            public void onFailure(String msg) {
                log.info(msg);
            }
        });
        return ResponseEntity.ok()
            .body("Request successfully!");
    }

    public ResponseEntity deployErrorAlert(String alertName, String time, String partition, String serverName) {
        String sql = "SELECT SUB_SYSTEM_ENAME FROM TEA00 WHERE SRV_ID='%s'";
        String param = serverName.split("_")[2];

        moduleNameService.getModule(partition, sql, param, new ModuleNameCallBack() {

            @Override
            public void onSuccess(DataTable table) {
                String module;
                if (table.getRows().size() == 0) {
                    log.debug("无module数据");
                    module = "EMPTY";
                } else {
                    module = table.getValue(0, "SUB_SYSTEM_ENAME").toString();
                }
                sendEmailAndMessage(alertName, module, partition, serverName, time, null, null, null);

            }

            @Override
            public void onFailure(String msg) {
                log.info(msg);
            }
        });
        return ResponseEntity.ok()
            .body("Request successfully!");
    }

    public ResponseEntity teleErrorAlert(String alertName, String time, String partition, String tcNo, String tcMsg) {
        sendEmailAndMessage(alertName, tcNo, partition, null, time, null, tcMsg, null);
        return ResponseEntity.ok()
            .body("Request successfully!");
    }

    public ResponseEntity teleTimeoutAlert(String alertName, String time, String partition, String tcNo, String tcTime) {
        sendEmailAndMessage(alertName, tcNo, partition, null, time, tcTime, null, null);
        return ResponseEntity.ok()
            .body("Request successfully!");
    }

    public ResponseEntity logAbnormalAlert(String alertName, String time, String partition, String es) {
        sendEmailAndMessage(alertName, null, partition, null, time, null, null, es);
        return ResponseEntity.ok()
            .body("Request successfully!");
    }

    public ResponseEntity commonAlert(AlertInfo alertInfo) {
        sendEmailAndMessage(alertInfo);
        return ResponseEntity.ok()
            .body("Request successfully!");
    }

    private void sendEmailAndMessage(AlertInfo alertInfo) {
        String alertName = alertInfo.getAlertName();
        String partition = alertInfo.getPartition();
        String module = alertInfo.getModule();
        List<Object[]> list1 = alertTypeRepository.findAlertInfo(alertName, partition, module);
        if (list1.size() == 0) {
            return;
        }
        for (Object[] objects : list1) {
            String userId = objects[1].toString();
            String to = objects[2].toString();
            String phone = objects[3].toString();
            String content = objects[4].toString();
            content = replaceMsgContent(content, alertInfo.getContentMap());
            String msgType = objects[5].toString();
            String subject = "多基地制造系统日志监控中心：" + objects[6].toString();
            String alertLink = objects[7].toString();
            alertLink = replaceMsgContent(alertLink, alertInfo.getContentMap());
            sendEmailAndMessageByMsgType(alertName, module, partition, userId, to, phone, content, msgType, subject, alertLink);

        }
    }


    private void sendEmailAndMessage(String alertName, String module, String partition, String svc,
                                     String time, String tcTime, String tcMsg, String es) {
        List<Object[]> list1 = alertTypeRepository.findAlertInfo(alertName, partition, module);
        if (list1.size() == 0) {
            return;
        }
        for (Object[] objects : list1) {
            String userId = objects[1].toString();
            String to = objects[2].toString();
            String phone = objects[3].toString();
            String content = objects[4].toString();
            if ("ServerDie".equals(alertName)) content = getServerDieMsg(content, module, partition, svc, time);
            if ("DeployError".equals(alertName)) content = getDeployErrorMsg(content, module, partition, svc, time);
            if ("TeleError".equals(alertName)) content = getTeleErrorMsg(content, time, partition, module, tcMsg);
            if ("TeleTimeout".equals(alertName)) content = getTeleTimeoutMsg(content, time, partition, module, tcTime);
            if ("LogAbnormal".equals(alertName)) content = getLogAbnormalMsg(content, time, partition, es);
            String msgType = objects[5].toString();
            String subject = "多基地制造系统日志监控中心：" + objects[6].toString();
            sendEmailAndMessageByMsgType(alertName, module, partition, userId, to, phone, content, msgType, subject, "");

        }
    }


    private void sendEmailAndMessageByMsgType(String alertName, String moduleName, String partition, String userId, String to,
                                              String phone, String content, String msgType, String subject, String alertLink) {
        if (msgType.equals("0")) {
            mailService.sendEmail(to, subject,  content + alertLink, false, true);
            saveAlertMemo(alertName, partition, moduleName, userId, Integer.valueOf(msgType),  content + alertLink);

        } else if (msgType.equals("1")) {
            msgConfigService.sendMessage(new String[]{phone}, content);
            saveAlertMemo(alertName, partition, moduleName, userId, Integer.valueOf(msgType), content);
        } else if (msgType.equals("2")) {
            mailService.sendEmail(to, subject,  content + alertLink, false, true);
            msgConfigService.sendMessage(new String[]{phone}, content);
            saveAlertMemo(alertName, partition, moduleName, userId, Integer.valueOf(msgType),  content + alertLink);
        }
    }

    private String getServerDieMsg(String content, String module, String partition, String svc, String time) {
        return getMsgContent(content, module, partition, svc, time, "", "", "", "");
    }

    private String getDeployErrorMsg(String content, String module, String partition, String svc, String time) {
        return getMsgContent(content, module, partition, svc, time, "", "", "", "");
    }

    private String getTeleErrorMsg(String content, String time, String partition, String tcNo, String tcMsg) {
        return getMsgContent(content, "", partition, "", time, tcNo, tcMsg, "", "");
    }

    private String getTeleTimeoutMsg(String content, String time, String partition, String tcNo, String tcTime) {
        return getMsgContent(content, "", partition, "", time, tcNo, "", tcTime, "");
    }

    private String getLogAbnormalMsg(String content, String time, String partition, String es) {
        return getMsgContent(content, "", partition, "", time, "", "", "", es);
    }

    private String replaceMsgContent(String content, Map<String, String> contentMap) {
        Set<String> ketSet = contentMap.keySet();
        for (String key : ketSet) {
            content = content.replace(key, contentMap.get(key));
        }
        return content;
    }

    private String getMsgContent(String content, String module, String partition, String svc,
                                 String time, String tcNo, String tcMsg, String tcTime, String es) {
        return content
            .replace("$time$", time)
            .replace("$partition_id$", partition)
            .replace("$svc_name$", svc)
            .replace("$module_name$", module)
            .replace("$tc_no$", tcNo)
            .replace("$tc_msg$", tcMsg)
            .replace("$tc_time$", tcTime)
            .replace("$es$", es)
            ;
    }

    private String getSvc(String partition, String pid) {
        BoolQueryBuilder builder = QueryBuilders.boolQuery();
        builder.filter(QueryBuilders.termQuery("partition", partition));
        builder.filter(QueryBuilders.termQuery("pid", pid));

        String index = "logstash-*-svcsql-*";
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
            .withIndices(index)
            .withTypes("log")
            .withQuery(builder)
            .withSort(SortBuilders.fieldSort("flag").order(SortOrder.DESC))
            .withPageable(new PageRequest(0, 1))
            .build();

        List<SvcName> list = StreamSupport.stream(svcNameSearchRepository.search(searchQuery).spliterator(), false)
            .collect(Collectors.toList());
        if (list.size() == 0) {
            log.info("getSvc():svc not found！");
            return null;
        } else {
            SvcName svcName = list.get(0);
            String svc = svcName.getSvc();
            Date logTime = DateUtil.stringToDate(svcName.getLogTime());
            Calendar cal = Calendar.getInstance();
            cal.set(Calendar.HOUR_OF_DAY, cal.get(Calendar.HOUR_OF_DAY) - 1);
            Date oneHourAgo = cal.getTime();
            if (oneHourAgo.after(logTime)) {
                log.info("logtime = " + logTime + "，out of one hour!");
                return null;
            }
            if (svc.startsWith("eb_")) {
                log.info("svc = " + svc);
                return null;
            }
            return svc;
        }

    }

    public void saveAlertMemo(String alertName, String partitionId, String moduleName, String userNo, Integer msgType, String alertMsg) {
        AlertMemo alertMemo = new AlertMemo();
        Timestamp recCreateTime = DateUtil.getTime();
        alertMemo.setRecCreateTime(recCreateTime);
        alertMemo.setAlertName(alertName);
        alertMemo.setPartitionId(partitionId);
        alertMemo.setModuleName(moduleName);
        alertMemo.setUserNo(userNo);
        alertMemo.setMsgType(msgType);
        alertMemo.setAlertMsg(alertMsg);
        alertMemoRepository.save(alertMemo);
    }


}
